#ifndef CLUSNET_NET_TCPACCEPTOR_H
#define CLUSNET_NET_TCPACCEPTOR_H

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <clusnet/base/ObjectPool.h>
#include <unordered_set>
#include "TcpConnection.h"

namespace clusnet
{
namespace net
{

class TcpServer;
class TcpAcceptor final
{
    public:
        TcpAcceptor(TcpServer*, boost::asio::io_context& io_context, const boost::asio::ip::tcp::endpoint& endpoint, bool reuseAddr = true, bool nodelay = true, bool keepAlive = false);
        ~TcpAcceptor();
        TcpAcceptor(const TcpAcceptor&) = delete;
        TcpAcceptor& operator= (const TcpAcceptor&) = delete;

    public:
        void setNewConnectionCallback(const TcpNewConnectionCallback& cb) { newConnCallback_ = cb; }
        void setWriteCompleteCallback(const TcpWriteCompleteCallback& cb) { writeCallback_ = cb; }
        void setMessageCallback(const TcpMessageCallback& cb) { messageCallback_ = cb; }
        void setCloseCallback(const TcpCloseCallback& cb) { closeCallback_ = cb; }

        void safeStartAccept();
        void safeStop(const std::function<void()>& cb);

    private:
        void handleAccept(TcpConnectionPtr conn, const boost::system::error_code& ec);
        void safeHandleClose(TcpConnectionPtr& conn);

    private:
        boost::asio::io_context::strand                 strand_;
        boost::asio::io_context&                        io_;
        boost::asio::ip::tcp::acceptor                  acceptor_;
        clusnet::base::ObjectPool<TcpConnection>        tcpConnPool_;

        TcpNewConnectionCallback                           newConnCallback_;
        TcpCloseCallback                                   closeCallback_;
        TcpWriteCompleteCallback                           writeCallback_;
        TcpMessageCallback                                 messageCallback_;
        bool    nodelay_;  
        bool    keepAlive_;
        bool    stop_;

        TcpServer*  server_;
};

}
}

#endif 
